package com.loto.insurance.oem.web.service;

import java.math.BigDecimal;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import com.loto.insurance.oem.web.entity.CustLoginLog;
import com.loto.insurance.oem.web.utils.WebUtils;
import com.loto.insurance.oem.web.db.mapper.CustExtInfoMapper;
import com.loto.insurance.oem.web.db.mapper.CustFeeFlowMapper;
import com.loto.insurance.oem.web.db.mapper.CustInfoMapper;
import com.loto.insurance.oem.web.db.mapper.CustLevelMapper;
import com.loto.insurance.oem.web.db.mapper.CustLoginLogMapper;
import com.loto.insurance.oem.web.db.mapper.OthersMapper;
import com.loto.insurance.oem.web.entity.CustExtInfo;
import com.loto.insurance.oem.web.entity.CustFeeFlow;
import com.loto.insurance.oem.web.entity.CustInfo;
import com.loto.insurance.oem.web.entity.CustLevel;
import com.loto.insurance.oem.web.entity.SessionUser;
import com.loto.insurance.oem.web.entity.ajax.BaseJson;
import com.loto.insurance.oem.web.enumeration.ControllerPropertyEnum;
import com.loto.insurance.oem.web.enumeration.FeeTypeEnum;
import com.loto.insurance.oem.web.enumeration.PayChannelEnum;
import com.loto.insurance.oem.web.enumeration.PayForEnum;
import com.loto.insurance.oem.web.enumeration.PaymentStatusEnum;
import com.loto.utils.DateUtils;
import com.loto.utils.MD5;

@Service
public class CustInfoService {

  static Logger logger = LogManager.getLogger(CustInfoService.class);

  @Autowired
  private CustInfoMapper custInfoMapper;

  @Autowired
  CustExtInfoMapper custExtInfoMapper;

  @Autowired
  CustLoginLogMapper custLoginLogMapper;

  @Autowired
  CustLevelMapper custLevelMapper;

  @Autowired
  OthersMapper othersMapper;

  @Autowired
  CustFeeFlowMapper custFeeFlowMapper;

  @Autowired
  DataSourceTransactionManager transactionManager;

  @Autowired
  private DefaultTransactionDefinition def;

  public BaseJson doLogin(HttpServletRequest request, String loginName,
	  String loginPwd) {
	BaseJson base = new BaseJson();
	base.setOk(false);
	base.setMsg(ControllerPropertyEnum.WRONG_USERNAME.toString());
	CustInfo custInfo = custInfoMapper.findActiveByName(loginName);
	if (custInfo == null)
	  return base;
	String pwd = custInfo.getCustPwd();
	if (pwd != null && !pwd.isEmpty()) {
	  if (pwd.toLowerCase().equals(MD5.GetMD5Code(loginPwd).toLowerCase())) {
		// session
		SessionUser user = new SessionUser();
		user.setUserId(custInfo.getCustId());
		user.setUsername(custInfo.getCustName());
		user.setRoleId(custInfo.getCustUserFlg());
		HttpSession session = request.getSession();
		session.setAttribute("oem_user", user);

		// 登录日志
		CustLoginLog loginLog = new CustLoginLog();
		loginLog.setLogCreatedBy(custInfo.getCustId());
		loginLog.setLogIp(WebUtils.getIpAddr(request));
		custLoginLogMapper.insertLog(loginLog);

		// 更新最后登录时间
		Calendar now = Calendar.getInstance();
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("custId", custInfo.getCustId());
		params.put("custLastActivedOn", now.getTime());
		custInfoMapper.updateCustLastLoginTime(params);

		base.setOk(true);
		base.setMsg("");
	  }
	}
	return base;
  }

  public BigDecimal getUsefulfee(long custId) {
	BigDecimal fee = new BigDecimal(0);
	CustInfo custInfo = custInfoMapper.findUsefulfeeById(custId);
	if (custInfo != null)
	  fee = custInfo.getCustUsefulFee();
	return fee;
  }

  public BaseJson changePwd(String custName, String oldPwd, String newPwd) {
	BaseJson base = new BaseJson();
	base.setOk(false);
	base.setMsg(ControllerPropertyEnum.WRONG_PWD.toString());
	CustInfo custInfo = custInfoMapper.findActiveByName(custName);
	String pwd = custInfo.getCustPwd();
	if (pwd != null && !pwd.isEmpty()
	    && pwd.toLowerCase().equals(MD5.GetMD5Code(oldPwd).toLowerCase())) {
	  // 修改密码
	  Map<String, Object> params = new HashMap<String, Object>();
	  params.put("custId", custInfo.getCustId());
	  params.put("newPwd", MD5.GetMD5Code(newPwd));
	  if (custInfoMapper.updateCustPwd(params) > 0) {
		base.setOk(true);
		base.setMsg("");
	  }
	}
	return base;
  }

  public long findAllCustCount(Map<String, Object> params) {
	return custInfoMapper.findAllCustPagerCount(params);
  }

  public List<CustInfo> findAllCust(Map<String, Object> params) {
	return custInfoMapper.findAllCustPager(params);
  }

  public CustInfo findById(long custId) {
	return custInfoMapper.findById(custId);
  }

  public CustExtInfo findExtById(long custId) {
	return custExtInfoMapper.findById(custId);
  }

  public List<CustLevel> findAllLevel() {
	return custLevelMapper.findAllLevel();
  }

  public BaseJson updateCustInfo(CustInfo custInfo, CustExtInfo custExtInfo) {
	BaseJson base = new BaseJson();
	base.setOk(false);

	// 取得当前调整的账户余额
	CustInfo currentCustInfo = custInfoMapper.findUsefulfeeById(custInfo
	    .getCustId());
	if (currentCustInfo == null) {
	  base.setOk(false);
	  base.setMsg(ControllerPropertyEnum.DATA_WRONG.getName());
	  return base;
	}

	// 取得admin余额
	CustInfo adminInfo = custInfoMapper.findUsefulfeeByName("admin");
	if (adminInfo == null) {
	  base.setOk(false);
	  base.setMsg(ControllerPropertyEnum.DATA_WRONG.getName());
	  return base;
	}
	BigDecimal adminUsefulFee = adminInfo.getCustUsefulFee();

	BigDecimal currentCustUsefulFee = currentCustInfo.getCustUsefulFee();
	// 调整金额=现在余额-要调整为的金额
	BigDecimal adjustFee = currentCustUsefulFee.subtract(custInfo
	    .getCustUsefulFee());

	Calendar now = Calendar.getInstance();
	TransactionStatus status = transactionManager.getTransaction(def);
	try {
	  // （1）调整金额=0，直接修改资料
	  // （2）调整金额>0，插入流后修改资料和admin余额
	  // （3）调整金额<0，要判断admin的余额是否足够，及与大后台余额是否一致，若一致则插入流后修改资料和admin余额

	  // （2）调整金额>0，插入流后修改资料和admin余额
	  if (adjustFee.compareTo(new BigDecimal(0)) > 0) {
		// 一笔admin余额调整
		String payNo = DateUtils.nowToCompactString() + othersMapper.getIndex();
		CustFeeFlow feeFlow = new CustFeeFlow();
		feeFlow.setFlowAfterFee(adminUsefulFee.add(adjustFee));
		feeFlow.setFlowBeforeFee(adminUsefulFee);
		feeFlow.setFlowChangedFee(adjustFee);
		feeFlow.setFlowChannel(PayChannelEnum.BALANCE.getName());
		feeFlow.setFlowCreditedOn(now.getTime());
		feeFlow.setFlowCustFid(adminInfo.getCustId());
		feeFlow.setFlowFlag(PaymentStatusEnum.SUC.getIndex());
		feeFlow.setFlowFor(PayForEnum.BALANCE.getIndex());
		feeFlow.setFlowMemo(FeeTypeEnum.BALANCE_ADJEST.getName());
		feeFlow.setFlowOutPayNo(payNo + "-"
		    + String.valueOf(adminInfo.getCustId()));
		feeFlow.setFlowPayNo(payNo + "-"
		    + String.valueOf(adminInfo.getCustId()));
		feeFlow.setFlowRelatedFid(0);
		feeFlow.setFlowType(FeeTypeEnum.BALANCE_ADJEST.getIndex());
		custFeeFlowMapper.insertCustFeeFlow(feeFlow);

		Map<String, Object> params = new HashMap<String, Object>();
		params.put("custId", adminInfo.getCustId());
		params.put("changedFee", adjustFee);
		custInfoMapper.updateUsefulfeeById(params);

		// 一笔当前用户流
		feeFlow = new CustFeeFlow();
		feeFlow.setFlowAfterFee(currentCustUsefulFee.subtract(adjustFee));
		feeFlow.setFlowBeforeFee(currentCustUsefulFee);
		feeFlow.setFlowChangedFee(adjustFee.subtract(adjustFee
		    .multiply(new BigDecimal(2))));
		feeFlow.setFlowChannel(PayChannelEnum.BALANCE.getName());
		feeFlow.setFlowCreditedOn(now.getTime());
		feeFlow.setFlowCustFid(custInfo.getCustId());
		feeFlow.setFlowFlag(PaymentStatusEnum.SUC.getIndex());
		feeFlow.setFlowFor(PayForEnum.BALANCE.getIndex());
		feeFlow.setFlowMemo(FeeTypeEnum.BALANCE_ADJEST.getName());
		feeFlow.setFlowOutPayNo(payNo + "-"
		    + String.valueOf(custInfo.getCustId()));
		feeFlow
		    .setFlowPayNo(payNo + "-" + String.valueOf(custInfo.getCustId()));
		feeFlow.setFlowRelatedFid(0);
		feeFlow.setFlowType(FeeTypeEnum.BALANCE_ADJEST.getIndex());
		custFeeFlowMapper.insertCustFeeFlow(feeFlow);
	  }

	  // （3）调整金额<0，要判断admin的余额是否足够，及与大后台余额是否一致，若一致则插入流后修改资料和admin余额
	  else if (adjustFee.compareTo(new BigDecimal(0)) < 0) {
		// BigDecimal totalUsefulFee = new BigDecimal(0);
		// TODO 从大后台取得可用余额
		/*
	     * Config config = new Config(); OEMConfig configFile =
	     * config.getConfigFile(ConfigFileEnum.OEMCONFIG, OEMConfig.class);
	     * 
	     * Base requestBase = new Base(); String xmlRequest =
	     * XML.toXML(requestBase, Base.class); logger.info(xmlRequest);
	     * 
	     * Map<String, String> paramMap = new HashMap<String, String>();
	     * paramMap.put("content", xmlRequest); String xmlResponse =
	     * Http.doPost(configFile.getOemPlatform() +
	     * "/webservice/queryusefulfee.service", paramMap);
	     * logger.info(xmlResponse); BaseJson response =
	     * XML.fromXML(xmlResponse, BaseJson.class); if (response != null &&
	     * response.isOk() && DecimalUtils.isDecimal(response.getMsg())) {
	     * totalUsefulFee = new BigDecimal(response.getMsg()); } List<Long> ids
	     * = new ArrayList<Long>(); ids.add(custInfo.getCustId());
	     * ids.add(adminInfo.getCustId());
	     * 
	     * // 取得除admin和当前用户外的总额 BigDecimal currentTotalUsefulFee =
	     * custInfoMapper .findUsefulfeeWithoutIds(ids);
	     */
		// 判断admin余额是否足够, //调整后的总额与大后台的总额是否一致 &&
		// currentTotalUsefulFee.add(currentCustUsefulFee.add(adminUsefulFee)).compareTo(totalUsefulFee)
		// == 0
		if (adminUsefulFee.compareTo(adjustFee) >= 0) {
		  // 一笔admin余额调整
		  String payNo = DateUtils.nowToCompactString()
			  + othersMapper.getIndex();
		  CustFeeFlow feeFlow = new CustFeeFlow();
		  feeFlow.setFlowAfterFee(adminUsefulFee.add(adjustFee));
		  feeFlow.setFlowBeforeFee(adminUsefulFee);
		  feeFlow.setFlowChangedFee(adjustFee);
		  feeFlow.setFlowChannel(PayChannelEnum.BALANCE.getName());
		  feeFlow.setFlowCreditedOn(now.getTime());
		  feeFlow.setFlowCustFid(adminInfo.getCustId());
		  feeFlow.setFlowFlag(PaymentStatusEnum.SUC.getIndex());
		  feeFlow.setFlowFor(PayForEnum.BALANCE.getIndex());
		  feeFlow.setFlowMemo(FeeTypeEnum.BALANCE_ADJEST.getName());
		  feeFlow.setFlowOutPayNo(payNo + "-"
			  + String.valueOf(adminInfo.getCustId()));
		  feeFlow.setFlowPayNo(payNo + "-"
			  + String.valueOf(adminInfo.getCustId()));
		  feeFlow.setFlowRelatedFid(0);
		  feeFlow.setFlowType(FeeTypeEnum.BALANCE_ADJEST.getIndex());
		  custFeeFlowMapper.insertCustFeeFlow(feeFlow);

		  Map<String, Object> params = new HashMap<String, Object>();
		  params.put("custId", adminInfo.getCustId());
		  params.put("changedFee", adjustFee);
		  custInfoMapper.updateUsefulfeeById(params);

		  // 一笔当前用户流
		  feeFlow = new CustFeeFlow();
		  feeFlow.setFlowAfterFee(currentCustUsefulFee.subtract(adjustFee));
		  feeFlow.setFlowBeforeFee(currentCustUsefulFee);
		  feeFlow.setFlowChangedFee(adjustFee.subtract(adjustFee
			  .multiply(new BigDecimal(2))));
		  feeFlow.setFlowChannel(PayChannelEnum.BALANCE.getName());
		  feeFlow.setFlowCreditedOn(now.getTime());
		  feeFlow.setFlowCustFid(custInfo.getCustId());
		  feeFlow.setFlowFlag(PaymentStatusEnum.SUC.getIndex());
		  feeFlow.setFlowFor(PayForEnum.BALANCE.getIndex());
		  feeFlow.setFlowMemo(FeeTypeEnum.BALANCE_ADJEST.getName());
		  feeFlow.setFlowOutPayNo(payNo + "-"
			  + String.valueOf(custInfo.getCustId()));
		  feeFlow.setFlowPayNo(payNo + "-"
			  + String.valueOf(custInfo.getCustId()));
		  feeFlow.setFlowRelatedFid(0);
		  feeFlow.setFlowType(FeeTypeEnum.BALANCE_ADJEST.getIndex());
		  custFeeFlowMapper.insertCustFeeFlow(feeFlow);
		} else {
		  base.setOk(false);
		  base.setMsg(ControllerPropertyEnum.LESS_USEFUL_FEE.getName());
		}
	  }
	  custInfoMapper.updateCustById(custInfo);
	  custExtInfoMapper.updateCustExtById(custExtInfo);
	  transactionManager.commit(status);
	  base.setOk(true);
	} catch (Exception e) {
	  e.printStackTrace();
	  transactionManager.rollback(status);
	  base.setOk(false);
	  base.setMsg(ControllerPropertyEnum.DATA_WRONG.getName());
	}
	return base;
  }

  public List<CustLevel> findAllLevelWithCount() {
	return custLevelMapper.findAllLevelWithCount();
  }

  public boolean levelIsFixed(int levelId) {
	boolean isFixed = true;
	CustLevel level = custLevelMapper.findLevelById(levelId);
	if (level != null && level.getLevelIsFixed() == 0) {
	  isFixed = false;
	}
	return isFixed;
  }

  public int updateLevel(int levelId, BigDecimal levelDiscount) {
	CustLevel custLevel = new CustLevel();
	custLevel.setLevelDiscount(levelDiscount);
	custLevel.setLevelId(levelId);
	return custLevelMapper.updateLevelWithoutName(custLevel);
  }

  public int updateLevel(int levelId, String levelName, BigDecimal levelDiscount) {
	CustLevel custLevel = new CustLevel();
	custLevel.setLevelDiscount(levelDiscount);
	custLevel.setLevelId(levelId);
	custLevel.setLevelName(levelName);
	return custLevelMapper.updateLevel(custLevel);
  }

  public int insertLevel(String levelName, BigDecimal levelDiscount) {
	if (custLevelMapper.findLevelByName(levelName) == null) {
	  CustLevel custLevel = new CustLevel();
	  custLevel.setLevelDiscount(levelDiscount);
	  custLevel.setLevelName(levelName);
	  return custLevelMapper.insertLevel(custLevel);
	} else
	  return 0;
  }

  public boolean isCustExisted(String custName) {
	if (custInfoMapper.findByName(custName) != null)
	  return true;
	else
	  return false;
  }

  public boolean isEmailExisted(String email) {
	if (custInfoMapper.findByEmail(email) != null)
	  return true;
	else
	  return false;
  }

  public BaseJson addCustInfo(CustInfo custInfo, CustExtInfo custExtInfo) {
	BaseJson base = new BaseJson();
	base.setOk(false);

	if (!isCustExisted(custInfo.getCustName())
	    && !isEmailExisted(custInfo.getCustEmail())) {

	  TransactionStatus status = transactionManager.getTransaction(def);
	  try {
		custInfoMapper.insertCust(custInfo);
		long custId = custInfo.getCustId();
		custExtInfo.setExtCustFid(custId);
		custExtInfoMapper.insertCustExt(custExtInfo);
		transactionManager.commit(status);
		base.setOk(true);
	  } catch (Exception e) {
		e.printStackTrace();
		transactionManager.rollback(status);
		base.setOk(false);
		base.setMsg(ControllerPropertyEnum.DATA_WRONG.getName());
	  }
	} else {
	  base.setOk(false);
	  base.setMsg(ControllerPropertyEnum.CUST_EXISTED.getName());
	}
	return base;
  }

  public BigDecimal findUsefulfeeByName(String name) {
	BigDecimal usefulfee = new BigDecimal(0);
	CustInfo custInfo = custInfoMapper.findUsefulfeeByName(name);
	if (custInfo != null)
	  usefulfee = custInfo.getCustUsefulFee();
	return usefulfee;
  }

  // 调整余额
  public boolean adjustFee(CustFeeFlow feeFlow) {
	TransactionStatus status = transactionManager.getTransaction(def);
	CustInfo custInfo = custInfoMapper.findByName("admin");
	if (custInfo != null) {
	  long custId = custInfo.getCustId();
	  try {
		feeFlow.setFlowCustFid(custId);
		long flowId = custFeeFlowMapper.insertCustFeeFlow(feeFlow);
		// 修改余额
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("custId", custId);
		params.put("changedFee", feeFlow.getFlowChangedFee());
		int re = custInfoMapper.updateUsefulfeeById(params);

		transactionManager.commit(status);
		return flowId > 0 && re > 0;

	  } catch (Exception ex) {
		ex.printStackTrace();
		transactionManager.rollback(status);
	  }
	}
	return false;
  }
}
